import ffmpeg
import os
import uuid
from PIL import Image
import logging

class ImageTools:
    """图像处理工具类"""
    
    def __init__(self):
        """初始化图像工具"""
        self.supported_image_formats = ['jpg', 'jpeg', 'png', 'bmp', 'gif', 'tiff', 'webp']
    
    def extract_frames(self, video_path, output_dir, fps=1):
        """
        从视频中提取帧
        
        Args:
            video_path (str): 视频文件路径
            output_dir (str): 输出目录
            fps (int): 每秒提取的帧数
            
        Returns:
            str: 输出目录路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            frames_dir = os.path.join(output_dir, f"frames_{uuid.uuid4().hex[:8]}")
            os.makedirs(frames_dir, exist_ok=True)
            
            # 使用FFmpeg提取帧
            output_pattern = os.path.join(frames_dir, 'frame_%04d.jpg')
            
            stream = ffmpeg.input(video_path)
            stream = ffmpeg.output(stream, output_pattern, vf=f'fps={fps}')
            ffmpeg.run(stream, overwrite_output=True, quiet=True)
            
            # 验证输出目录是否存在
            if not os.path.exists(frames_dir):
                raise Exception(f"FFmpeg处理完成但输出目录不存在: {frames_dir}")
            
            return frames_dir
        except Exception as e:
            raise Exception(f"提取帧失败: {str(e)}")
    
    def create_gif(self, video_path, output_dir, duration=10, fps=10):
        """
        从视频创建GIF
        
        Args:
            video_path (str): 视频文件路径
            output_dir (str): 输出目录
            duration (int): GIF持续时间（秒）
            fps (int): GIF帧率
            
        Returns:
            str: 输出GIF文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            output_filename = f"gif_{uuid.uuid4().hex[:8]}.gif"
            output_path = os.path.join(output_dir, output_filename)
            
            # 使用FFmpeg创建GIF
            stream = ffmpeg.input(video_path, t=duration)
            stream = ffmpeg.output(stream, output_path, vf=f'fps={fps},scale=320:-1:flags=lanczos')
            ffmpeg.run(stream, overwrite_output=True, quiet=True)
            
            # 验证输出文件是否存在
            if not os.path.exists(output_path):
                raise Exception(f"FFmpeg处理完成但输出文件不存在: {output_path}")
            
            return output_path
        except Exception as e:
            raise Exception(f"创建GIF失败: {str(e)}")
    
    def convert_image_format(self, image_path, target_format, output_dir):
        """
        转换图像格式
        
        Args:
            image_path (str): 图像文件路径
            target_format (str): 目标格式
            output_dir (str): 输出目录
            
        Returns:
            str: 输出图像文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            output_filename = f"converted_image_{uuid.uuid4().hex[:8]}.{target_format}"
            output_path = os.path.join(output_dir, output_filename)
            
            # 检查目标格式是否支持
            if target_format.lower() not in self.supported_image_formats:
                raise ValueError(f"不支持的图像格式: {target_format}")
            
            # 使用PIL转换图像格式
            with Image.open(image_path) as img:
                # 如果是RGBA模式且目标格式不支持透明度，转换为RGB
                if img.mode == 'RGBA' and target_format.lower() in ['jpg', 'jpeg']:
                    img = img.convert('RGB')
                
                img.save(output_path, format=target_format.upper())
            
            # 验证输出文件是否存在
            if not os.path.exists(output_path):
                raise Exception(f"图像转换完成但输出文件不存在: {output_path}")
            
            return output_path
        except Exception as e:
            raise Exception(f"转换图像格式失败: {str(e)}")
    
    def resize_image(self, image_path, width, height, output_dir, keep_aspect_ratio=True):
        """
        调整图像尺寸
        
        Args:
            image_path (str): 图像文件路径
            width (int): 目标宽度
            height (int): 目标高度
            output_dir (str): 输出目录
            keep_aspect_ratio (bool): 是否保持宽高比
            
        Returns:
            str: 输出图像文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            output_filename = f"resized_image_{uuid.uuid4().hex[:8]}.jpg"
            output_path = os.path.join(output_dir, output_filename)
            
            # 使用PIL调整图像尺寸
            with Image.open(image_path) as img:
                if keep_aspect_ratio:
                    # 保持宽高比
                    img.thumbnail((width, height), Image.Resampling.LANCZOS)
                else:
                    # 强制调整到指定尺寸
                    img = img.resize((width, height), Image.Resampling.LANCZOS)
                
                img.save(output_path, 'JPEG', quality=95)
            
            # 验证输出文件是否存在
            if not os.path.exists(output_path):
                raise Exception(f"图像调整完成但输出文件不存在: {output_path}")
            
            return output_path
        except Exception as e:
            raise Exception(f"调整图像尺寸失败: {str(e)}")
    
    def get_image_info(self, image_path):
        """
        获取图像信息
        
        Args:
            image_path (str): 图像文件路径
            
        Returns:
            dict: 图像信息
        """
        try:
            with Image.open(image_path) as img:
                info = {
                    'format': img.format,
                    'mode': img.mode,
                    'width': img.width,
                    'height': img.height,
                    'size': os.path.getsize(image_path)
                }
                
                # 获取更多信息
                if hasattr(img, 'info'):
                    info.update(img.info)
                
                return info
        except Exception as e:
            raise Exception(f"获取图像信息失败: {str(e)}")
    
    def create_thumbnail(self, video_path, output_dir, time_position='00:00:05', width=320, height=240):
        """
        从视频创建缩略图
        
        Args:
            video_path (str): 视频文件路径
            output_dir (str): 输出目录
            time_position (str): 提取帧的时间位置，格式为 "HH:MM:SS"
            width (int): 缩略图宽度
            height (int): 缩略图高度
            
        Returns:
            str: 输出缩略图文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            output_filename = f"thumbnail_{uuid.uuid4().hex[:8]}.jpg"
            output_path = os.path.join(output_dir, output_filename)
            
            # 使用FFmpeg创建缩略图
            stream = ffmpeg.input(video_path, ss=time_position)
            stream = ffmpeg.output(stream, output_path, vframes=1, s=f'{width}x{height}')
            ffmpeg.run(stream, overwrite_output=True, quiet=True)
            
            # 验证输出文件是否存在
            if not os.path.exists(output_path):
                raise Exception(f"FFmpeg处理完成但输出文件不存在: {output_path}")
            
            return output_path
        except Exception as e:
            raise Exception(f"创建缩略图失败: {str(e)}")
    
    def remove_watermark(self, video_path, x, y, width, height, output_dir):
        """
        去除视频水印
        
        Args:
            video_path (str): 视频文件路径
            x (int): 水印左上角x坐标
            y (int): 水印左上角y坐标
            width (int): 水印宽度
            height (int): 水印高度
            output_dir (str): 输出目录
            
        Returns:
            str: 输出视频文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            output_filename = f"no_watermark_{uuid.uuid4().hex[:8]}.mp4"
            output_path = os.path.join(output_dir, output_filename)
            
            # 使用FFmpeg去除水印（通过模糊处理）
            filter_complex = f"boxblur=10:10:{x}:{y}:{width}:{height}"
            
            stream = ffmpeg.input(video_path)
            stream = ffmpeg.output(stream, output_path, vf=filter_complex)
            ffmpeg.run(stream, overwrite_output=True, quiet=True)
            
            # 验证输出文件是否存在
            if not os.path.exists(output_path):
                raise Exception(f"FFmpeg处理完成但输出文件不存在: {output_path}")
            
            return output_path
        except Exception as e:
            raise Exception(f"去除水印失败: {str(e)}") 